package graph;

public class Graph {//Граф
	private int current_id = 0;//счетчик ID вершин
	
	class VertexNode{//Вершины графа
		private Vertex vertex;//Вершина
		private VertexNode next_vertex;//Следующая вершина
		private String vertex_name;//Имя вершины
		//Конструкторы
		public VertexNode(){
			this.vertex_name = "";
			this.next_vertex = null;
			this.vertex = new Vertex(current_id);
			++current_id;
		}
		public VertexNode(String vertex_name){
			this.vertex_name = vertex_name;
			this.next_vertex = null;
			this.vertex = new Vertex(current_id);
			++current_id;
		}
		//Геттер и сеттер для вершины
		public Vertex getVertex(){
			return this.vertex;
		}
		public void setVertex(Vertex vertex){//Сеттер по вершине
			this.vertex = vertex;
		}
		public void setVertes(int id){//Сеттер по ID
			this.vertex = new Vertex(id);
		}
		//Геттер и сеттер для следующей вершины
		public VertexNode getNextVertex(){
			return this.next_vertex;
		}
		public void setNextVertex(VertexNode next_vertex){
			this.next_vertex = next_vertex;
		}
		//Геттер и сеттер для имени вершины
		public String getVertexName(){
			return this.vertex_name;
		}
		public void setVertexName(String vertex_name){
			this.vertex_name = vertex_name;
		}
	}
	
	private VertexNode head;//Первая вершина
	private int vertex_count;//Количество вершин
	//Конструктор, создает пустой граф
	public Graph(){
		head = null;
		this.vertex_count = 0;
	}
	//Геттер для количества вершин
	public int getVertexCount(){
		return this.vertex_count;
	}
	//Проверка, существует ли в графе вершина с заданным ID
	public boolean isVertexExistById(int id){
		VertexNode temp = this.head;
		while(temp != null){
			if(temp.getVertex().getId() == id){
				return true;
			}
			temp = temp.getNextVertex();
		}
		return false;
	}
	//Доступ к вершине по ID, null, если такой вершины нет
	public Vertex getVertexById(int id){
		VertexNode temp = this.head;
		while(temp != null){
			if(temp.getVertex().getId() == id){
				return temp.getVertex();
			}
			temp = temp.getNextVertex();
		}
		return null;
	}
	//Проверка, существует ли в графе вершина с заданным Именем
	public boolean isVertexExistByName(String vertex_name){
		VertexNode temp = this.head;
		while(temp != null){
			if(temp.getVertexName().equals(vertex_name)){
				return true;
			}
			temp = temp.getNextVertex();
		}
		return false;
	}
	//Доступ к вершине по Имени, null если такой вершины нет
	public Vertex getVertexByName(String vertex_name){
		int temp = this.getIdByName(vertex_name);
		return this.getVertexById(temp);
	}
	//Получение ID по Имени
	public int getIdByName(String vertex_name){
		if(this.isVertexExistByName(vertex_name)){
			VertexNode temp = this.head;
			while(temp != null){
				if(temp.getVertexName().equals(vertex_name)){
					return temp.getVertex().getId();
				}
				temp = temp.getNextVertex();
			}
		}
		else{
			return -1;
		}
		return -2;
	}
	//Получение Имени по ID
	public String getNameById(int id){
		if(this.isVertexExistById(id)){
			VertexNode temp = this.head;
			while(temp != null){
				if(temp.getVertex().getId() == id){
					return temp.getVertexName();
				}
				temp = temp.getNextVertex();
			}
		}
		else{
			return "";
		}
		return"";
	}
	//Добавить новую вершину
	public void addNewVertex(String vertex_name){
		if(this.head == null){
			this.head = new VertexNode(vertex_name);
			this.vertex_count++;
			return;
		}
		if(this.isVertexExistByName(vertex_name) == false){
			VertexNode temp = this.head;
			while(temp.getNextVertex() != null){
				temp = temp.getNextVertex();
			}
			temp.setNextVertex(new VertexNode(vertex_name));
			this.vertex_count++;
		}
	}
	//Добавить новое ребро
	public void addNewEdge(int id_a, int id_b, int distance){
		if((this.isVertexExistById(id_a) && this.isVertexExistById(id_b)) == true){
			Vertex vertex_a = this.getVertexById(id_a);
			Vertex vertex_b = this.getVertexById(id_b);
			if((vertex_a.isSonExist(id_b) || vertex_b.isSonExist(id_a)) == true){
				return;
			}
			vertex_a.addNewSon(vertex_b, distance);
			vertex_b.addNewSon(vertex_a, distance);			
		} 
	}
	//Возвращает максимальное значение ID
	public int getMaxId(){
		return current_id;
	}
}
